#pragma once
#include "index.hpp"
#include <algorithm>
#include <json/json.h>

namespace Searcher
{
    struct InvertedElemPrint
    {
        uint64_t id;                         //文档的ID
        std::vector<std::string> words;      //文档中的关键字
        int weight;                          //权重
        InvertedElemPrint() : id(0), weight(0){}                   
    };

    class searcher
    {
    private:
        Index::index* index;
    public:
        searcher(){}
        ~searcher(){}

        void InitSearcher(const std::string& input)
        {
            //1.创建对象
            index = Index::index::GetInstance();
            LOG(NORMAL, "创建单例对象成功");
            //2.构建索引
            index->BuildIndex(input);
            LOG(NORMAL, "构建索引成功");
        }

        void search(const std::string& query, std::string* json_string)
        {
            //1.分词
            std::vector<std::string> words;
            Util::CutUtil::CutString(query, &words);
            //2.触发：找到文档内容
            //Index::InvertedList inverted_elem_all;
            std::vector<InvertedElemPrint> inverted_elem_all;
            std::unordered_map<uint64_t, InvertedElemPrint> tokens_map;
            for(auto word : words)
            {
                boost::to_lower(word);
                Index::InvertedList* inverted_list = index->GetInvertedList(word);
                if(nullptr == inverted_list)
                    continue;

                for(const auto& elem: *inverted_list)
                {
                    auto& item = tokens_map[elem.id];
                    item.id = elem.id;
                    item.weight += elem.weight;
                    item.words.push_back(elem.word);
                }
                std::cout << std::endl;
                //inverted_elem_all.insert(inverted_elem_all.end(), inverted_list->begin(), inverted_list->end());
            }
            for(const auto& elem : tokens_map)
            {
                inverted_elem_all.push_back(std::move(elem.second));
            }
            //3.合并，降序排序
            struct cmp
            {
                bool operator()(const InvertedElemPrint& e1,const InvertedElemPrint& e2)
                {
                    return e1.weight > e2.weight;
                }
            };
            std::sort(inverted_elem_all.begin(), inverted_elem_all.end(), cmp());
            //4.构建json返回给用户
            Json::Value root;
            for(auto& inverted_elem : inverted_elem_all)
            {
                Index::DocInfo* doc = index->GetDocInfo(inverted_elem.id);
                if(nullptr == doc)
                    continue;
                Json::Value item;
                item["title"] = doc->title;
                item["desc"] = GetDesc(doc->content, inverted_elem.words[0]);
                item["url"] = doc->url;
                //for debug
                //item["id"] = (int)inverted_elem.id;
                //item["weight"] = inverted_elem.weight;

                root.append(item);
            }
            Json::FastWriter writer;
            *json_string = writer.write(root);
        }

        std::string GetDesc(const std::string& content, const std::string& word)
        {
            const int prev_step = 50;
            const int next_step = 100;
            auto iter = std::search(content.begin(), content.end(), word.begin(), word.end(), [](const int x, const int y){
                return std::tolower(x) == std::tolower(y);
            });
            if(iter == content.end())
                return "None1"; 
            int pos = std::distance(content.begin(), iter);
            int start = 0;
            int end = content.length()-1;
            if(start + prev_step < pos)
                start = pos - prev_step;
            if(pos + next_step < end)
                end = pos + next_step;
            if(start >= end)
                return "None2"; //不可能发生的

            std::string ret = content.substr(start, end-start);
            ret += "...";

            return ret;
        }
    };
}